package com.bjpowernode.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bjpowernode.entity.PmsProduct;
import com.bjpowernode.entity.PmsSkuStore;
import com.bjpowernode.feign.FileService;
import com.bjpowernode.mapper.PmsProductMapper;
import com.bjpowernode.service.PmsBrandService;
import com.bjpowernode.service.PmsCategoryService;
import com.bjpowernode.service.PmsProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjpowernode.service.PmsSkuStoreService;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author zs
 * @since 2024-06-25
 */
@Service
public class PmsProductServiceImpl extends ServiceImpl<PmsProductMapper, PmsProduct> implements PmsProductService {

    //注入文件服务，用于上传文件图片相册
    @Resource
    FileService fileService;

    //注入品牌服务，用于根据品牌id查询品牌名称
    @Resource
    PmsBrandService pmsBrandService;

    //注入分类服务，用于分类id查询分类名称
    @Resource
    PmsCategoryService pmsCategoryService;

    //注入SKU库存服务，用于录入SKU库存信息数据
    @Resource
    PmsSkuStoreService pmsSkuStoreService;

    @Override
    //在具体业务层中，添加事务注解，则此方法会被事务所管理。需要录入N多条记录，为保证多条数据插入成功，需要开启事务。
    @Transactional//添加事务注解
    public Boolean save(String name, BigDecimal price, String brandId, String[] categoryId, MultipartFile[] files, String[] spu, String[] sku, String description, String[] skuArray) throws IOException {
        PmsProduct pmsProduct = new PmsProduct();
        //1.保存商品
        /*1.1 保存不需要额外处理的字段*/
        pmsProduct.setName(name);
        pmsProduct.setPrice(price);
        pmsProduct.setBrandId(brandId);
        pmsProduct.setDescription(description);

        /*1.2 保存数组相关的字段【因为MySQL不支持数组的字段类型所以将数组转换json串保存到表中】*/
        pmsProduct.setCategoryId(JSONObject.toJSONString(categoryId));
        pmsProduct.setSku(JSONObject.toJSONString(sku));
        pmsProduct.setSpu(JSONObject.toJSONString(spu));

        /*1.3 保存相册的字段album（文件Files）*/
        //创建集合保存文件遍历的多张文件图片
        List<String> albumList = new ArrayList<>();
        for (MultipartFile file :
                files) {//遍历目的是相册是包括多张图片文件，所以需要遍历
            //System.out.println(file.getName());  图片上传过程中，得到的是getName是files，而不是file则相同数据无录入数据库，所以需要对每个遍历出的file进行重构，将name属性设置为file
            String fileUrl = fileService.imageUpload(new MockMultipartFile("file", file.getOriginalFilename(), file.getContentType(), file.getInputStream()));
            albumList.add(fileUrl);
        }
        pmsProduct.setAlbum(JSONObject.toJSONString(albumList));

        /*1.3 保存品牌名称以及分类名称*/
        String brandName = pmsBrandService.getNameById(brandId);
        pmsProduct.setBrandName(brandName);
        //categoryId为数组，所以数据保存形式为1/2/3，为一组数据
        String categoryName = pmsCategoryService.getNameById(categoryId);
        pmsProduct.setCategoryName(categoryName);

        /*1.3 保存商品*/
        this.save(pmsProduct);

        //2.保存库存（此顺序原因是要现有商品再有库存）
        List<PmsSkuStore> storeList = new ArrayList<>();
        //将skuArrayjson数组中每个Json数据串转换为单独的json对象，对象中包含各个库存属性，将属性保存到库存表中
        for (String store : skuArray) {
            //我们不单独拆分json串，因为json字符串中包含多个属性数据及数组
            //将json串转换为json对象，将json对象的属性拆分并生成到对应实体类对象的对应的属性中
            PmsSkuStore pmsSkuStore = JSONObject.parseObject(store, PmsSkuStore.class);//反射的使用，PmsSkuStore.class相当于new一个此对象，将store的属性保存到此对象中
            //生成商品后，商品表则自动生成外键商品id
            pmsSkuStore.setProductId(pmsProduct.getId());
            storeList.add(pmsSkuStore);
        }
        return pmsSkuStoreService.saveBatch(storeList);
    }

    //分页查询商品列表
    @Override
    public IPage list(Integer pageNo, Integer pageSize) {
        QueryWrapper<PmsProduct> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("sort");
        return this.page(new Page<>(pageNo, pageSize), wrapper);
    }

    //更新商品状态
    @Override
    public Boolean changeStatus(String id, Boolean isPublish) {
        return this.updateById(new PmsProduct(id, isPublish));
    }

    @Override
    public Boolean updateBase(String id, String name, BigDecimal price, String brandId) {
        PmsProduct pmsProduct = new PmsProduct(id, name, price, brandId);
        pmsProduct.setBrandName(pmsBrandService.getNameById(brandId));
        return this.updateById(pmsProduct);
    }

    @Override
    public Boolean updateSpu(String id, String[] spu) {
        PmsProduct pmsProduct = new PmsProduct();
        pmsProduct.setId(id);
        pmsProduct.setSpu(JSONObject.toJSONString(spu));
        return this.updateById(pmsProduct);
    }


    //更新商品相册--将新图的文件保存进入mino中，并将mino返回的新图路径（从返回的路径中取得新图的name）保存到数据库中
    //老图的name已经存在，新图和老图的name不一样，所以现在需要新图的name，然后将新图的name加入到老图的names中
    @Override
    public Boolean updateAlbum(String id, String[] names, MultipartFile[] files) throws IOException {
        //创建集合保存文件遍历的多张文件图片
        List<String> album = new ArrayList<>();
        //进行判断是否有添加的新图，是否有删除后剩余的旧图
        if (null != names) {
            for (String name : names) {
                album.add(name);
            }

        }
        if (null != files) {
            for (MultipartFile file :
                    files) {
                String url = fileService.imageUpload(new MockMultipartFile("file", file.getOriginalFilename(), file.getContentType(), file.getInputStream()));
                album.add(url);
            }
        }
        PmsProduct pmsProduct = new PmsProduct();
        pmsProduct.setId(id);
        pmsProduct.setAlbum(JSONObject.toJSONString(album));

        return this.updateById(pmsProduct);
    }

    @Override
    public Boolean updateDescription(String id, String description) {
        PmsProduct pmsProduct = new PmsProduct();
        pmsProduct.setId(id);
        pmsProduct.setDescription(description);

        return this.updateById(pmsProduct);
    }
}
